(* ========================================================================
                  Universal Stream Package Format Utilites
                               for GLScene
   ------------------------------------------------------------------------
     File: uPackageUtils.pas
     Copyright: (c) 2010, TSX Software
     License: Freeware
   ======================================================================== *)
unit uPackageUtils;

interface

uses uPackage, GLCrossPlatform, GLVectorFileObjects, GLTexture;

type
  TPersistentLoadMode = (
    pmAlways,    // Always load image into memory
    pmOnlyPlain, // Load into memory if not compressed
    pmNever      // Never load to memory
                 // Note! This may be slow at large compressed images
  );

function LoadMeshFromUSFEntry(const Source: TUSFPackageEntry; const Dest: TGLBaseMesh): boolean;
function LoadTexImageFromUSFEntry(const Source: TUSFPackageEntry; const Dest: TGLTexture;
  const Persistent: TPersistentLoadMode = pmOnlyPlain): boolean;

function USFTextureToGLGraphic(const Source: TUSFPackageEntry): TGLGraphic;

implementation

uses Classes, Graphics, DDS, TGA, GLUSFSourceImage,
  GLFile3DS, GLFileSTL, GLFileASE,
  GLFileSMD, GLFileMD2, GLFileMD5;

function USFTextureToGLGraphic(const Source: TUSFPackageEntry): TGLGraphic;
var s: TStream;
begin
  Result := nil;
  if not (Source is TUSFTextureEntry) then exit;

  try
    case TUSFTextureEntry(Source).TextureFormat of
      utDXT1,utDXT3,utDXT5,
      utDXTC{, utDX10}: Result := TDDSImage.Create;
      utTGA: Result := TTGAImage.Create;
      utP8,utRGB,utRGBA: Result := TBitmap.Create;
    end;

    if not Source.Compressed then
      s := Source.AsLegacyStream
    else begin
      s := TMemoryStream.Create;
      Source.CopyToStream(s);
    end;
    s.Seek(0, soFromBeginning);
    try
      Result.LoadFromStream(s);
    finally
      s.Free;
    end;
  except end;
end;

function LoadMeshFromUSFEntry(const Source: TUSFPackageEntry; const Dest: TGLBaseMesh): boolean;
var s: TStream;
    fn: string;
begin
  Result := false;
  if not (Source is TUSFMeshEntry) then exit;

  try
    case TUSFMeshEntry(Source).MeshFormat of
      um3DS: fn := 'file.3ds';
      umASE: fn := 'file.ase';
      umSTL: fn := 'file.stl';
      umSMD: fn := 'file.smd';
      umMD2: fn := 'file.md2';
      umMD5: fn := 'file.md5mesh';
      else fn := '';
    end;
    if fn = '' then exit; // Unsupported mesh

    if not Source.Compressed then
      s := Source.AsLegacyStream
    else begin
      s := TMemoryStream.Create;
      try
        Source.CopyToStream(s);
      except
        s.Free;
        exit;
      end;
    end;
    
    try
      s.Seek(0, soFromBeginning);
      Dest.LoadFromStream(fn, s);
      Result := true;
    finally
      s.Free;
    end;

  except end;
end;

function LoadTexImageFromUSFEntry(const Source: TUSFPackageEntry; const Dest: TGLTexture;
  const Persistent: TPersistentLoadMode): boolean;
var gr: TGLGraphic;
begin
  Result := false;
  if not (Source is TUSFTextureEntry) then exit;

  case Persistent of
    pmAlways: Dest.ImageClassName := TGLPersistentImage.ClassName;
    pmOnlyPlain: if Source.Compressed then Dest.ImageClassName := TGLPersistentImage.ClassName
                 else Dest.ImageClassName := TGLUSFSourceImage.ClassName;
    pmNever: Dest.ImageClassName := TGLUSFSourceImage.ClassName;
  end;

  if (Dest.ImageClassName = TGLPersistentImage.ClassName) then begin
    gr := USFTextureToGLGraphic(Source);
    if Assigned(gr) then begin
      TGLPersistentImage(Dest.Image).Assign(gr);
      gr.Free;
      Result := true;
    end;
    exit;
  end;

  if (Dest.ImageClassName = TGLUSFSourceImage.ClassName) then begin
    TGLUSFSourceImage(Dest.Image).UseTextureEntry := TUSFTextureEntry(Source);
    Result := true;
    exit;
  end
end;

end.